package cc.bukkitPlugin.banitem.command.analyse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;

import org.bukkit.command.CommandSender;

import cc.bukkitPlugin.banitem.BanItem;
import cc.bukkitPlugin.banitem.command.AParamCommand;
import cc.bukkitPlugin.util.plugin.ABukkitPlugin;

public class AnalyseMan{

    private BanItem mPlugin;
    private final HashMap<String,AParam> mModels=new HashMap<>();

    public AnalyseMan(BanItem pPlugin){
        this.mPlugin=pPlugin;
        this.register(new ParamDamage(pPlugin,this));
        this.register(new ParamItem(pPlugin,this));
        this.register(new ParamNBTLabel(pPlugin,this));
        this.register(new ParamNBTValue(pPlugin,this));
        this.register(new ParamReason(pPlugin,this));
        this.register(new ParamListType(pPlugin,this));
        this.register(new ParamWorld(pPlugin,this));
    }

    /**
     * 注册一个参数处理模块
     * @param pModel 模块实例
     * @param pLabel 模块标签
     */
    protected void register(AParam pModel){
        AParam tModel=null;
        String[] tLabels=pModel.getLabels();
        if(tLabels==null||tLabels.length==0){
            ABukkitPlugin.severe("命令参数解析模块["+pModel.getClass().getSimpleName()+"]未设置解析的标签");
            return;
        }
        for(String sLabel : tLabels){
            if((tModel=this.mModels.put(sLabel,pModel))!=null)
                ABukkitPlugin.warn("注册参数解析模块时发生了标签重复,重复了["+tModel.getClass().getSimpleName()+"]与["+pModel.getClass().getSimpleName()+"]的["+sLabel+"]");
            this.mModels.put(sLabel.toLowerCase(),pModel);
        }
    }

    /**
     * 根据参数模块标签(不包含冒号)获取参数模块实例
     * @param pClazzParam 类
     */
    public AParam getParamModel(String pLabel){
        pLabel=pLabel.toLowerCase();
        return this.mModels.get(pLabel);
    }

    /**
     * 根据参数模块类获取参数模块实例
     * @param pClazzParam 类
     */
    public AParam getParamModel(Class<? extends AParam> pClazzParam){
        for(AParam sModel : this.mModels.values())
            if(sModel.getClass()==pClazzParam)
                return sModel;
        ABukkitPlugin.severe("未注册命令参数解析模块"+pClazzParam.getSimpleName());
        return null;
    }

    /**
     * 获取命令解析模块标签的拷贝
     */
    public Set<String> keySet(){
        return new HashSet<String>(this.mModels.keySet());
    }

    /**
     * 获取所有命令解析模块
     */
    public Set<AParam> valueSet(){
        return new HashSet<AParam>(this.mModels.values());
    }

    public Set<Entry<String,AParam>> entrySet(){
        return this.mModels.entrySet();
    }

    /**
     * 根据参数生成命令参数类,该函数不会发送消息
     * <p>
     * {@link AnalyseResult#mBuildError}表示表示在建立时是否出错<br />
     * {@link AnalyseResult#mBuildErrorMsg}存储建立参数出错时的消息
     * </p>
     * @param pSender 发送者
     * @param pArgs 参数
     */
    public AnalyseResult buildParam(CommandSender pSender,AParamCommand pCommand,String[] pArgs){
        return this.buildParam(pSender,pCommand,pArgs,false);
    }

    /**
     * 根据参数生成命令参数类,该函数不会发送消息
     * <p>
     * {@link AnalyseResult#mBuildError}表示表示在建立时是否出错<br />
     * {@link AnalyseResult#mBuildErrorMsg}存储建立参数出错时的消息
     * </p>
     * @param pSender 发送者
     * @param pArgs 参数
     * @param pIgnoreError 忽视错误
     */
    public AnalyseResult buildParam(CommandSender pSender,AParamCommand pCommand,String[] pArgs,boolean pIgnoreError){
        AnalyseResult tCmdParam=new AnalyseResult();
        for(String sArg : pArgs){
            String[] subParam=sArg.split(":",2);
            if(subParam.length<=1){
                if(pIgnoreError)
                    continue;
                return tCmdParam.buildError("&c参数["+sArg+"]格式不正确");
            }
            AParam tModel=this.getParamModel(subParam[0]);
            if(!pIgnoreError&&tModel==null||!pCommand.isParamAllow(tModel.getClass())){
                if(pIgnoreError)
                    continue;
                return tCmdParam.buildError("&c未知的参数选项["+subParam[0]+"]");
            }
            tCmdParam=tModel.handle(pSender,tCmdParam,subParam[1]);
            if(tCmdParam.mBuildError){
                if(pIgnoreError)
                    continue;
                return tCmdParam.buildError("&c参数["+sArg+"]错误: "+tCmdParam.mBuildErrorMsg);
            }
        }
        return tCmdParam.buildSuccess();
    }

    /**
     * 获取所有参数模块的帮助
     */
    public ArrayList<String> getHelp(){
        ArrayList<String> helps=new ArrayList<>();
        ArrayList<AParam> handled=new ArrayList<>();
        for(AParam tModel : this.mModels.values()){
            if(handled.contains(tModel))
                continue;
            handled.add(tModel);
            helps.addAll(tModel.getHelp());
        }
        return helps;
    }

    /**
     * 获取包括" : "符号在内的所有可用参数
     */
    public ArrayList<String> getParams(AParamCommand pCommand){
        ArrayList<String> params=new ArrayList<>();
        for(Entry<String,AParam> entry : this.mModels.entrySet()){
            if(!pCommand.isParamAllow(entry.getValue().getClass()))
                continue;
            params.add(entry.getKey()+":");
        }
        return params;
    }

}
